home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok58.lha / EasyRexx / EasyRexx.mod < prev    next >
Text File  |  1993-08-15  |  7KB  |  258 lines

  1. MODULE EasyRexx;
  2.  
  3. IMPORT rsl := RexxSysLib,
  4.        e * := Exec,
  5.        es  := ExecSupport,
  6.        rx  := Rexx,
  7.        str := Strings,
  8.        avl := AVL;
  9.  
  10. CONST
  11.   errorImGone = 100;
  12.   errorNoCmd  = 30;
  13.  
  14. TYPE
  15.   String * = e.STRING;
  16.  
  17.   RexxCommandPtr * = POINTER TO RexxCommand;
  18.  
  19.   UserProc * = PROCEDURE(comm: RexxCommandPtr;
  20.                          args: String;
  21.                          VAR result: String);
  22.  
  23.   RexxCommand * = RECORD (avl.SNode)
  24.                     proc * : UserProc;
  25.                   END;
  26.  
  27. VAR
  28.   rexxPort : e.MsgPortPtr;           (* this is *our* rexx port           *)
  29.   commands : avl.SRoot;              (* our command list (actually a tree *)
  30.  
  31.   outStandingRMsg : rx.RexxMsgPtr;   (* the outstanding Rexx message *)
  32.  
  33.  
  34. (*---------------------------------------------------------------------------*)
  35.  
  36.  
  37. PROCEDURE OpenRexx * (name: String): LONGSET;
  38. (*
  39.  * Öffnet AREXX-Port mit Namen 'name'. Ergebnis ist das Signal des Ports
  40.  * (bereits in der LONGSET-Memge gesetzt).
  41.  * Konnte der Port nicht geöffnet werden, weil ein Port mit gleichen Namen
  42.  * bereits existiert oder weil zu wenig Speicher vorhanden war, wird
  43.  * eine leere Menge zurückgegeben.
  44.  *)
  45.  
  46. VAR
  47.   Name: POINTER TO String;
  48.  
  49. BEGIN
  50.  
  51.   IF rexxPort = NIL THEN
  52.  
  53.     e.Forbid() ;
  54.       IF e.FindPort(name)=NIL THEN    (* existiert gleichnamiger Port? *)
  55.         NEW(Name);
  56.         IF Name#NIL THEN              (* Speicher für Name             *)
  57.           Name^ := name;
  58.           rexxPort := es.CreatePort(Name^, 0)  (* Port erzeugen        *)
  59.         END;
  60.       END;
  61.     e.Permit() ;
  62.  
  63.   END;
  64.  
  65.   IF rexxPort # NIL THEN
  66.  
  67.     RETURN LONGSET{rexxPort.sigBit}                (* Signalset zurück *)
  68.  
  69.   ELSE
  70.  
  71.     RETURN LONGSET{}                                      (* leere Set *)
  72.  
  73.   END;
  74.  
  75. END OpenRexx;
  76.  
  77.  
  78. (*---------------------------------------------------------------------------*)
  79.  
  80.  
  81. PROCEDURE AddCommand * (comm: RexxCommandPtr);
  82. (*
  83.  * Fügt ein REXX-Command an die Commandoliste an. comm muß auf eine mit
  84.  * NEW() allozierten RECORD zeigen. In dem RECORD müssen die Felder
  85.  * comm.name für den Commandoname und comm.proc für die aufzurufende
  86.  * Prozedur ausgefüllt werden. comm.proc bekommt die eigene Struktur
  87.  * comm als ersten Parameter übergeben, so daß man durch Erweiterung
  88.  * von comm noch weitere Werte an die Prozedur übergeben kann.
  89.  *
  90.  * Commandos mit gleichen Namen dürfen nur 1 mal mit AddCommand()
  91.  * aktiviert werden, ansonsten bricht das Programm mit rc=20 ab.
  92.  *
  93.  *)
  94.  
  95. BEGIN
  96.  
  97.   IF NOT avl.Add(commands,comm) THEN HALT(20) END;
  98.  
  99. END AddCommand;
  100.  
  101.  
  102. (*---------------------------------------------------------------------------*)
  103.  
  104.  
  105. PROCEDURE EasyAddCommand*(name: ARRAY OF CHAR; proc: UserProc): BOOLEAN;
  106. (*
  107.  * Fügt ähnlich AddCommand() ein REXX-Commando an Commandoliste an.
  108.  * Hier wird jedoch lediglich ein standard-RexxCommand erzeugt und
  109.  * das Record kann vom Benutzer nicht erweitert werden.
  110.  *
  111.  * Ergebnis ist FALSE, wenn zu wenig Speicher vorhanden war.
  112.  *
  113.  *)
  114.  
  115. VAR
  116.   comm: RexxCommandPtr;
  117.  
  118. BEGIN
  119.  
  120.   NEW(comm); IF comm=NIL THEN RETURN FALSE END;
  121.  
  122.   comm.proc := proc;
  123.   COPY(name,comm.name);
  124.   AddCommand(comm);
  125.  
  126.   RETURN TRUE;
  127.  
  128. END EasyAddCommand;
  129.  
  130.  
  131. (*---------------------------------------------------------------------------*)
  132.  
  133.  
  134. PROCEDURE HandleRexx*;
  135. (*
  136.  * Dies Prozedur bearbeitet ankommende Rexx-Commandos. Sie sollte immer dann
  137.  * aufgerufen werden, wenn man den Verdacht hat, daß REXX-Messages angekommen
  138.  * sein könnten. Dies ist z.B. nach dem Aufruf von Exec.Wait(SignalSet+XYZ)
  139.  * der Fall, wenn SignalSet der von OpenRexxPort() erhaltene LONGSET ist.
  140.  *
  141.  * HandleRexxMsg ruft die mit AddCommand() aktivierten Prozeduren auf.
  142.  *
  143.  *)
  144.  
  145. VAR
  146.   RexxMsg: rx.RexxMsgPtr;
  147.   name: avl.String;
  148.   args,result: String;
  149.   i : INTEGER;
  150.   comm: avl.NodePtr;
  151.  
  152. BEGIN
  153.  
  154.   IF rexxPort = NIL THEN RETURN END;         (* kein Port -> keine Msg *)
  155.  
  156.   LOOP
  157.  
  158.     RexxMsg := e.GetMsg(rexxPort);                (* nächste Msg holen *)
  159.     IF RexxMsg=NIL THEN EXIT END;          (* keine mehr, dann tschüß! *)
  160.  
  161.     args := RexxMsg.args[0]^;                  (* Argumentstring holen *)
  162.  
  163.     i := 0;            (* Führende Spaces und Sonderzeichen übergehen: *)
  164.     WHILE (args[i] # 0X) AND (args[i] <= " ") DO INC(i) END;
  165.     str.Delete(args,0,i);
  166.  
  167.     i := 0;                               (* Commandoname extrahieren: *)
  168.     WHILE (args[i] # 0X) AND (args[i] >  " ") DO INC(i) END;
  169.  
  170.     COPY(args,name);                         (* Commandoname nach name *)
  171.     name[i] := 0X;
  172.  
  173.             (* Spaces und Sonderzeichen bis zum 1. Argument übergehen: *)
  174.     WHILE (args[i] # 0X) AND (args[i] <= " ") DO INC(i) END;
  175.     str.Delete(args,0,i);
  176.  
  177.     RexxMsg.result1 := 0 ;                        (* Result vorbelegen *)
  178.     RexxMsg.result2 := 0 ;
  179.  
  180.             (* Msg als unbearbeitet markieren, falls Command abbricht: *)
  181.     outStandingRMsg := RexxMsg ;
  182.  
  183.     comm := avl.SFind(commands,name);              (* Commando suchen: *)
  184.  
  185.     IF comm=NIL THEN                  (* nicht gefunden: Fehler melden *)
  186.  
  187.       RexxMsg.result1 := errorNoCmd;
  188.  
  189.     ELSE
  190.  
  191.       result := "";                       (* Ergebnisstring vorbelegen *)
  192.       WITH comm: RexxCommand DO
  193.         comm.proc(comm,args,result);             (* Commando ausführen *)
  194.       END;
  195.  
  196. (* Wenn Ergebnis vorhanden und von Rexx erwartet, Erbebnis abschicken: *)
  197.       IF (result#"") AND ODD(RexxMsg.action DIV rx.rxResult)  THEN
  198.         RexxMsg.result2 := rsl.CreateArgstring(result,str.Length(result));
  199.       END;
  200.  
  201.     END;   (* IF comm=NIL THEN ... ELSE *)
  202.  
  203.     outStandingRMsg := NIL;                      (* Msg ist bearbeitet *)
  204.     e.ReplyMsg(RexxMsg);                            (* und beantworten *)
  205.  
  206.   END;   (* LOOP, nach nächste Msg schauen. *)
  207.  
  208. END HandleRexx;  (* das war's *)
  209.  
  210.  
  211. (*---------------------------------------------------------------------------*)
  212.  
  213.  
  214. PROCEDURE CloseRexx*;
  215. (*
  216.  * Schließt mit OpenRexx() geöffneten AREXX-Port.
  217.  *)
  218.  
  219. VAR
  220.   name: e.STRPTR;
  221.  
  222. BEGIN
  223.   IF rexxPort=NIL THEN RETURN END;                        (* kein Port *)
  224.   IF outStandingRMsg#NIL THEN                   (* unbeantwortete Msg? *)
  225.     outStandingRMsg.result1 := errorImGone;          (* Fehler liefern *)
  226.     e.ReplyMsg(outStandingRMsg) ;                  (* und beantworten. *)
  227.     outStandingRMsg := NIL;
  228.   END;
  229.   e.Forbid;
  230.     LOOP
  231.       outStandingRMsg := e.GetMsg (rexxPort);
  232.       IF outStandingRMsg=NIL THEN EXIT END;
  233.       outStandingRMsg.result1 := errorImGone;        (* Fehler liefern *)
  234.       e.ReplyMsg(outStandingRMsg) ;                (* und beantworten. *)
  235.     END;
  236.     name := rexxPort.node.name;  (* Zeiger auf Portname (wg. Speicher) *)
  237.     es.DeletePort(rexxPort);                         (* Port schließen *)
  238.   e.Permit;
  239.   DISPOSE(name);                                     (* Name freigeben *)
  240.   rexxPort := NIL;
  241. END CloseRexx;
  242.  
  243.  
  244. (*---------------------------------------------------------------------------*)
  245.  
  246.  
  247. BEGIN                                              (* Initialisierung: *)
  248.  
  249.   avl.SInit(commands);
  250.   outStandingRMsg := NIL;
  251.   rexxPort := NIL;
  252.  
  253. CLOSE                                                      (* Cleanup: *)
  254.  
  255.   CloseRexx;
  256.  
  257. END EasyRexx.
  258.